import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.Before;
import org.junit.After;
/**
 *This class  implements is the test cases for VendingMachine class
 *
 */

public class VendingMachineTest {
        //Declaring variable of type VendingMachine     
        VendingMachine vm;
        //Declaring variable of type VendingMachineItem
        VendingMachineItem vmi_item;

        //creating new instance of VendingMachine and VendingMachineItem before running a test case
        @Before
        public void setUp() throws Exception {
                vm = new VendingMachine();
                vmi_item = new VendingMachineItem("Snickers",1.0);
        }
        //Tests If you add an item with an invalid code
        @Test (expected=VendingMachineException.class)
         public void testGetSLotIndex(){
                vm.addItem(vmi_item,"E");
                assertEquals(vmi_item,vm.getItem("E"));
        }
        //Tests if item add to the vending machine when slot is empty, given a valid code
        @Test
        public void testAddItem (){
                vm.addItem(vmi_item,"A");
                assertEquals(vmi_item,vm.getItem("A"));
        }
        
        //Tests if item add to the vending machine when slot is empty, given a valid code B
        @Test
        public void testAddItem_B (){
                vm.addItem(vmi_item,"B");
                assertEquals(vmi_item,vm.getItem("B"));
        }
        
        //Tests if item add to the vending machine when slot is empty, given a valid code B
        @Test
        public void testAddItem_C (){
                vm.addItem(vmi_item,"C");
                assertEquals(vmi_item,vm.getItem("C"));
        }
        
        //Tests if item add to the vending machine when slot is empty, given a valid code C
        @Test
        public void testAddItem_D (){
                vm.addItem(vmi_item,"C");
                assertEquals(vmi_item,vm.getItem("C"));
        }
        
        //Tests If you add an item with an invalid code
        @Test (expected=VendingMachineException.class)
         public void testAddItem_invalidCode (){
                vm.addItem(vmi_item,"D");
                assertEquals(vmi_item,vm.getItem("E"));
        }
        
        //Tests If you add an item to a slot that is already occupied
        @Test (expected=VendingMachineException.class)
        public void testAddItem_valid_Multiple (){
                vm.addItem(vmi_item,"A");
                vm.addItem(vmi_item,"A");
                assertEquals(vmi_item,vm.getItem("A"));
        }
        
        //Tests if removes item from a slot for a given code when slot is not is empty
        @Test 
        public void testRemoveItem(){
                vm.addItem(vmi_item,"A");
                vm.removeItem("A");
                assertEquals(null,vm.getItem("A"));
        }
        
        //Tests If removes item from a slot given an invalid code 
        @Test (expected=VendingMachineException.class)
         public void testRemoveItem_invalidCode (){
                vm.addItem(vmi_item,"A");
                vm.removeItem("E");
                assertEquals(null,vm.getItem("E"));
        }
                
        //Tests If removes item from a slot already empty
        @Test (expected=VendingMachineException.class)
        public void testRemoveItem_empty (){
                //adding item to a slot
                vm.addItem(vmi_item,"A");
                //removing item from a slot
                vm.removeItem("A");
                //removing from a slot that is already empty
                vm.removeItem("A");
                assertEquals(null,vm.getItem("A"));
        }
        
     //Tests if it works when a valid amount(greater than zero) is inserted     
         @Test    
         public void testInsertMoney() {
                 vm.insertMoney(1.0);
                 double balance=0.0;
                 balance= balance + 1.0;
                 assertEquals(balance,vm.balance,0);          
         }
         
         //Tests if it works when an invalid amount(less than zero) is inserted
         @Test (expected=VendingMachineException.class)        
         public void testInsertMoney_invalid() {
                 vm.insertMoney(-1.0); 
                 assertEquals(-1.0,vm.balance,0);          
        }
         
        //Tests if it works when an amount is equal to zero is inserted
        @Test        
        public void testInsertMoney_zeroPrice() {  
                vm.insertMoney(0.0); 
                double balance=0.0;
                balance= balance + 0.0;
                assertEquals(balance,vm.balance,0);         
        }     

        ////Tests if it returns balance in the machine when an amount of money is inserted
        @Test          
        public void testGetBalance() {                  
                vm.insertMoney(1.00);                  
                assertEquals( 1.00, vm.getBalance(),0);          
        }  
         
        //Tests if it works when a valid amount of money is inserted
        @Test          
        public void testMakePurchase() {//
                vm.addItem(vmi_item, "A");
                vm.insertMoney(2.00);  
                assertTrue(vm.makePurchase("A"));          
        } 
         
        //Tests if it works when money less than the price is inserted
         @Test          
         public void testMakePurchase_lessMoney() {
                 vm.addItem(vmi_item, "A");
                 vm.insertMoney(.50);  
                 assertFalse(vm.makePurchase("A"));          
        } 
         
        //Tests if it works when money less than the price is inserted
         @Test          
         public void testMakePurchase_emptySlot() {
                 vm.addItem(vmi_item, "A");
                 vm.removeItem("A");
                 vm.insertMoney(2.00);  
                 assertFalse(vm.makePurchase("A"));          
        } 
         
        //Tests if it returns change with a valid amount of  money
         @Test          
         public void testReturnChange() {                  
                 vm.addItem(vmi_item, "A");                                    
                 vm.insertMoney(2.00); 
                 vm.makePurchase("A");       
                 assertEquals(1.00, vm.returnChange(),0);          
        }  
         
        //Tests if it works when there is no change to return
         @Test          
         public void testReturnChange_noChange() {                  
                 vm.addItem(vmi_item, "A");                                    
                 vm.insertMoney(1.00); 
                 vm.makePurchase("A");       
                 assertEquals(0.00, vm.returnChange(),0);          
        }
         
        //Clearing any previous value of vmi_item after a test case completed running
        @After
        public void tearDown() throws Exception {
                vm=null;        
        }


}